﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BEELab.Data;
using System.Data;
using System.Data.SqlClient;
using System.Text;

namespace BEELab.Logic.ProgramManagement.StageManagement
{
    public static class ContainerManagement
    {
        public static int CreateContainer(int StageID, string Type, string Name, int FunctionID)
        {
            SqlCommand command = new SqlCommand();
            command.CommandText = "INSERT INTO Containers (StageID, Type, Name, FunctionID) VALUES (@StageID, @Type, @Name, @FunctionID); SELECT SCOPE_IDENTITY();";
            command.Parameters.Add(new SqlParameter("@StageID", StageID));
            command.Parameters.Add(new SqlParameter("@Type", Type));
            command.Parameters.Add(new SqlParameter("@Name", Name));
            command.Parameters.Add(new SqlParameter("@FunctionID", FunctionID));

            string res = DBHelper.ExecuteScalar(command);

            if (res == null)
                return -1;

            return int.Parse(res);
        }

        /// <summary>
        /// Gets container ID and delete it from DB
        /// </summary>
        /// <param name="ID">Container ID</param>
        /// <returns>True if succeeded, False otherwise</returns>
        public static Boolean DeleteContainer(int ID)
        {
            SqlCommand command = new SqlCommand();
            command = new SqlCommand();
            command.CommandText = "DELETE FROM Variables WHERE ID IN (SELECT ElementID FROM ContainerElements WHERE Type='Variable' AND ContainerID=@ContainerID); DELETE FROM BlockElements WHERE ID IN (SELECT ElementID FROM ContainerElements WHERE Type='BlockElement' AND ContainerID=@ContainerID); DELETE FROM PresentationElements WHERE ID IN (SELECT ElementID FROM ContainerElements WHERE Type='PresentationElement' AND ContainerID=@ContainerID); DELETE FROM Containers WHERE ID=@ContainerID;";
            command.Parameters.Add(new SqlParameter("@ContainerID", ID));

            int res = DBHelper.ExecuteNonQuery(command);

            if (res > 0)
                return true;

            return false;
        }

        public static Boolean AddElement(int ContainerID, string Type, int ElementID, string OriginalName)
        {
            SqlCommand command = new SqlCommand();
            command.CommandText = "INSERT INTO ContainerElements (ContainerID, Type, ElementID, OriginalName) VALUES (@ContainerID, @Type, @ElementID, @OriginalName)";
            command.Parameters.Add(new SqlParameter("@ContainerID", ContainerID));
            command.Parameters.Add(new SqlParameter("@Type", Type));
            command.Parameters.Add(new SqlParameter("@ElementID", ElementID));
            command.Parameters.Add(new SqlParameter("@OriginalName", OriginalName));

            int res = DBHelper.ExecuteNonQuery(command);

            if (res == 1)
                return true;

            return false;
        }

        public static Boolean ValidateName(string Name, int StageID)
        {
            int ProgramID = StageManagement.GetProgramID(StageID);

            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT Containers.Name FROM Containers JOIN Stages ON Containers.StageID=Stages.ID WHERE Stages.ProgramID=@ProgramID AND Containers.Name=@Name";
            command.Parameters.Add(new SqlParameter("@Name", Name));
            command.Parameters.Add(new SqlParameter("@ProgramID", ProgramID));
            
            DataTable res = DBHelper.ExecuteQuery(command);

            if (res.Rows.Count == 0)
                return true;

            return false;
        }

        public static Boolean RemoveElement(string Type, int ElementID)
        {
            SqlCommand command = new SqlCommand();
            command.CommandText = "DELETE FROM ContainerElements WHERE Type=@Type AND ElementID=@ElementID";
            command.Parameters.Add(new SqlParameter("@Type", Type));
            command.Parameters.Add(new SqlParameter("@ElementID", ElementID));

            int res = DBHelper.ExecuteNonQuery(command);

            if (res > 0)
                return true;

            return false;
        }

        public static List<KeyValuePair<int, string>> ListByContainerID(int ID)
        {
            List<KeyValuePair<int, string>> result = new List<KeyValuePair<int, string>>();

            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT ElementID, Type FROM ContainerElements WHERE ContainerID=@ContainerID";
            command.Parameters.Add(new SqlParameter("@ContainerID", ID));
            DataTable dt = DBHelper.ExecuteQuery(command);

            foreach (DataRow dr in dt.Rows)
            {
                result.Add(new KeyValuePair<int,string>(int.Parse(dr["ElementID"].ToString()), dr["Type"].ToString()));
            }

            return result;
        }

        /// <summary>
        /// Gets Stage ID and seperator, and returns String of all containers
        /// names on current stage, seperated by seperator.
        /// </summary>
        /// <param name="StageID">Stage ID</param>
        /// <param name="separator">separator</param>
        /// <returns>String of all containers names on current stage</returns>
        public static string EnumerateContainersForStage(int StageID, string separator)
        {
            StringBuilder res = new StringBuilder();

            int ProgramID = StageManagement.GetProgramID(StageID);

            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT Containers.Name FROM Containers JOIN Stages ON Containers.StageID=Stages.ID WHERE Stages.ProgramID=@ProgramID";
            command.Parameters.Add(new SqlParameter("@ProgramID", ProgramID));

            DataTable dt = DBHelper.ExecuteQuery(command);

            bool isFirst = true;

            foreach (DataRow row in dt.Rows)
            {
                if (!isFirst)
                {
                    res.Append(separator);
                }
                else
                {
                    isFirst = false;
                }
                res.Append(row[0].ToString());
                res.Append("$");
            }

            return res.ToString();
        }

        public static List<int> ListByStageID(int ID)
        {
            List<int> result = new List<int>();

            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT ID FROM Containers WHERE StageID=@StageID";
            command.Parameters.Add(new SqlParameter("@StageID", ID));
            DataTable dt = DBHelper.ExecuteQuery(command);

            foreach (DataRow dr in dt.Rows)
            {
                result.Add((int)dr["ID"]);
            }

            return result;
        }

        public static void DuplicateContainer(int ToStageID, int ContainerID, Dictionary<int, int> IDDictionary, bool ReplicateVariables, Dictionary<int, int> VariablesDictionary)
        {
            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT * FROM Containers WHERE ID=@ID";
            command.Parameters.Add(new SqlParameter("@ID", ContainerID));
            DataTable dt = DBHelper.ExecuteQuery(command);

            if (dt == null || dt.Rows.Count != 1)
                return;

            DataRow dr = dt.Rows[0];

            int ToID = CreateContainer(ToStageID, dr["Type"].ToString(), dr["Name"].ToString(), int.Parse(dr["FunctionID"].ToString()));

            ReplicateContainer(ContainerID, ToID, IDDictionary, ReplicateVariables, VariablesDictionary);
        }

        public static void ReplicateContainer(int FromID, int ToID, Dictionary<int, int> BlockElementsDictionary, bool ReplicateVariables, Dictionary<int, int> VariablesDictionary)
        {
            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT * FROM ContainerElements WHERE ContainerID=@ContainerID";
            command.Parameters.Add(new SqlParameter("@ContainerID", FromID));
            DataTable dt = DBHelper.ExecuteQuery(command);

            foreach (DataRow dr in dt.Rows)
            {
                if (dr["Type"].ToString() != "Variable")
                {
                    AddElement(ToID, dr["Type"].ToString(), BlockElementsDictionary[int.Parse(dr["ElementID"].ToString())], dr["OriginalName"].ToString());
                }
                else if (ReplicateVariables)
                {
                    AddElement(ToID, dr["Type"].ToString(), VariablesDictionary[int.Parse(dr["ElementID"].ToString())], dr["OriginalName"].ToString());
                }
            }
        }

    }
}